package com.scrapy4j.htmlp.extract;

import lombok.Data;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 正文内容提取
 *
 * 基于行块统计的正文提取算法的实现
 */
@Data
public class Content {
    int depth           = 5;// 每 5 行计统计一次字符数量
    int limitStartCount = 160; // 起始阈值
    int limitEndCount   = 10;// 结束阈值

    String body;// 原始网页BODY内容

    String txt          = "";// 用于存储正文纯文本
    String content      = "";// 用于存储正文带标签的内容

    public Content(String body) {
        this.body = body;
    }

    public static Content parse(String body) {
        return new Content(body).extract();
    }

    public Content extract() {
        int startPos = -1;
        int endPos = -1;

        // todo: 多个峰值的优化

        List<String> orgLines = new ArrayList<String>(); // 原始网页内容
        List<String> lines = new ArrayList<String>(); // 过滤掉标签的内容

        // 过滤 body 中包含的 script,style,注释 标签
        body = body.replaceAll("<script[\\s\\S]+?</script>", "");
        body = body.replaceAll("<style[\\s\\S]+?</style>", "");
        body = body.replaceAll("<svg[\\s\\S]+?</svg>", "");
        body = body.replaceAll("<!--[\\s\\S]+?-->", "");

        // 处理回车
        orgLines = Arrays.asList(body.split("\\n"));
        for (int i = 0; i < orgLines.size() - depth; i++) {
            String line = "";
            int wordsNum = 0;// 指定行数的字符串数量统计
            for (int j = i; j < i + depth; j++) {
                // 过滤无用标签
                line = orgLines.get(j);
                line = line.replaceAll("<.*?>", "")
                        .replaceAll("[ ]+", "")
                        .replaceAll("&.{2,5};|&#.{2,5};", "");
                wordsNum += line.length();
                if(i == j) {
                    lines.add(i, line);
                }
            }

            if(startPos == -1) {// 还没提取到正文起始位置的话，先计算正文起始位置
                if(wordsNum >= limitStartCount) {
                    startPos = i;
                }
            } else if(endPos == -1) {
                if(wordsNum == 0) {
                    endPos = i;
                }
            }
        }


        for (int i = startPos; i < endPos; i++) {
            content += orgLines.get(i);
            txt += lines.get(i);
        }

        return this;
    }
}
